package jwt

import (
	"errors"
	"fmt"
	"github.com/astaxie/beego/logs"
	"github.com/golang-jwt/jwt"
	"io/ioutil"
	"time"
	v1 "wonlicsys/api/v1"
	"wonlicsys/constPack"
)

type MyClaims struct {
	AdminID uint32
	UserName string
	jwt.StandardClaims
}
//Has 加密
//var jwtKey = []byte("base64:A0NsGA2Ys6Zuo9o3FETpFiUYIBsRzyFxfqOgggaPX+s=")
const TokenExpireDuration = time.Hour * 24 * 7


//生成jwt
func GetToken(adminId uint32,UserName string) (string,error) {

	logs.Debug(constPack.BaseConfPath + v1.Conf.PrivatePemPath,"调试")
	priBytes, err := ioutil.ReadFile(constPack.BaseConfPath + v1.Conf.PrivatePemPath)
	if err != nil {
		return "", errors.New("私钥文件读取失败")
	}
	jwtKey, err := jwt.ParseRSAPrivateKeyFromPEM(priBytes)
	if err != nil {
		return "", errors.New("私钥文件不正确")
	}

	c := &MyClaims{
		adminId,
		UserName,
		jwt.StandardClaims{
			IssuedAt:  time.Now().Unix(),
			ExpiresAt: time.Now().Add(TokenExpireDuration).Unix(),
			Issuer : "127.0.0.1",
			Subject:   "user token", //签名主题
		},
	}
	//Rsa 加密 SigningMethodRS256
	//Has SigningMethodHS256
	token := jwt.NewWithClaims(jwt.SigningMethodRS256,c)
	tokenString, err :=  token.SignedString(jwtKey)
	if err != nil {
		return "", err
	}
	return tokenString,err
}

//解析jwt
func ParseToken(tokenString string) (*MyClaims,error) {
	pubBytes, err := ioutil.ReadFile(constPack.BaseConfPath + v1.Conf.PublicPemPath)
	if err != nil {
		return nil, errors.New("公钥文件读取失败")
	}
	jwtKey, err := jwt.ParseRSAPublicKeyFromPEM(pubBytes)
	if err != nil {
		return nil, errors.New("公钥文件不正确")
	}
	// 解析token
	token, err := jwt.ParseWithClaims(tokenString, &MyClaims{}, func(token *jwt.Token) (i interface{}, err error) {
		return jwtKey, nil
	})

	if err != nil {
		// https://gowalker.org/github.com/dgrijalva/jwt-go#ValidationError
		// jwt.ValidationError 是一个无效token的错误结构
		if ve, ok := err.(*jwt.ValidationError); ok {
			// ValidationErrorMalformed是一个uint常量，表示token不可用
			if ve.Errors&jwt.ValidationErrorMalformed != 0 {
				return nil, fmt.Errorf("token不可用")
				// ValidationErrorExpired表示Token过期
			} else if ve.Errors&jwt.ValidationErrorExpired != 0 {
				return nil, fmt.Errorf("token过期")
				// ValidationErrorNotValidYet表示无效token
			} else if ve.Errors&jwt.ValidationErrorNotValidYet != 0 {
				return nil, fmt.Errorf("无效的token")
			} else {
				return nil, fmt.Errorf("token不可用")
			}

		}
	}
	if claims, ok := token.Claims.(*MyClaims); ok && token.Valid { // 校验token
		return claims, nil
	}
	return nil, errors.New("invalid token")
}

